package cn.tedu.store.order.webapi.service.impl;

import cn.tedu.store.commons.ex.ServiceException;
import cn.tedu.store.commons.pojo.order.dto.OrderAddNewDTO;
import cn.tedu.store.commons.pojo.order.dto.OrderItemAddDTO;
import cn.tedu.store.commons.pojo.order.dto.OrderListTimeDTO;
import cn.tedu.store.commons.pojo.order.dto.OrderUpdateStatusDTO;
import cn.tedu.store.commons.pojo.order.entity.Cart;
import cn.tedu.store.commons.pojo.order.entity.Order;
import cn.tedu.store.commons.pojo.order.entity.OrderItem;
import cn.tedu.store.commons.pojo.order.vo.OrderAddVO;
import cn.tedu.store.commons.pojo.order.vo.OrderListVO;
import cn.tedu.store.commons.pojo.product.entity.Sku;
import cn.tedu.store.commons.web.JsonPage;
import cn.tedu.store.commons.web.ServiceCode;
import cn.tedu.store.order.service.ICartService;
import cn.tedu.store.order.service.IOrderService;
import cn.tedu.store.order.webapi.mapper.OrderItemMapper;
import cn.tedu.store.order.webapi.mapper.OrderMapper;
import cn.tedu.store.order.webapi.security.LoginPrincipal;
import cn.tedu.store.order.webapi.utils.IdGeneratorUtils;
import cn.tedu.store.product.service.ISkuService;
import com.github.pagehelper.PageHelper;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class OrderServiceImpl implements IOrderService {

    @DubboReference
    private ISkuService skuService;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private ICartService cartService;

    @GlobalTransactional
    @Override
    public OrderAddVO addOrder(OrderAddNewDTO orderAddNewDTO) {
        Order order = new Order();
        BeanUtils.copyProperties(orderAddNewDTO, order);
        completingOrder(order);
        //将商品条目信息存入orderItem
        List<OrderItem> orderItems = new ArrayList<>();
        List<OrderItemAddDTO> itemAddDTOs = orderAddNewDTO.getOrderItems();
        if(itemAddDTOs == null || itemAddDTOs.isEmpty()){
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST,"订单中至少要包含一件商品!");
        }
        for (OrderItemAddDTO item : itemAddDTOs) {
            OrderItem orderItem = new OrderItem();
            BeanUtils.copyProperties(item,orderItem);
            orderItem.setOrderId(order.getId());
            orderItem.setId(IdGeneratorUtils.getDistributeId("order_item"));
            orderItems.add(orderItem);
            //减少库存
            Long skuId = orderItem.getSkuId();
            skuService.reduceStockById(skuId, orderItem.getQuantity());
            //删除购物车中的商品
            Cart cart = new Cart();
            cart.setUserId(order.getUserId());
            cart.setSkuId(skuId);
            cartService.removeUserCarts(cart);
        }
        //TODO 减少用户积分+赠送的积分
        //TODO 删除用户使用的优惠券
        orderMapper.insertOrder(order);//存储订单信息
        orderItemMapper.insertOrderItemList(orderItems);//存储所有商品条目

        //封装返回给前端订单信息
        OrderAddVO orderAddVO = new OrderAddVO();
        orderAddVO.setId(order.getId());
        orderAddVO.setSn(order.getSn());
        orderAddVO.setCreateTime(order.getCreateTime());
        orderAddVO.setPayAmount(order.getPayAmount());
        orderAddVO.setUseIntegration(order.getUseIntegration());
        order.setCouponAmount(order.getCouponAmount());
        return orderAddVO;
    }
    private void completingOrder(Order order){
        //leaf生成订单id
        order.setId(IdGeneratorUtils.getDistributeId("order"));
        //生成sn
        order.setSn(UUID.randomUUID().toString());
        // 赋值UserId
        if (order.getUserId() == null) {
            order.setUserId(getUserId());
        }
        // 为订单状态赋值,默认未支付
        if (order.getStatus() == null){
            order.setStatus(0);
        }
        //时间赋值
        LocalDateTime now = LocalDateTime.now();
        order.setCreateTime(now);
        order.setModifiedTime(now);
        //计算实际需支付金额
        BigDecimal total = order.getTotalAmount();//原总价
        BigDecimal freight = order.getFreightAmount();//运费
        BigDecimal integrationAmount = order.getIntegrationAmount();//积分抵扣金额
        BigDecimal couponAmount = order.getCouponAmount();//优惠券抵扣
        //实际应付金额
        BigDecimal payAmount = total.add(freight).subtract(integrationAmount).subtract(couponAmount);
        order.setPayAmount(payAmount);
    }

    @Override
    public void updateOrder(OrderUpdateStatusDTO orderUpdateStatusDTO) {
        Order order = new Order();
        BeanUtils.copyProperties(orderUpdateStatusDTO,order);
        orderMapper.updateOrderById(order);
    }

    @Override
    public JsonPage<OrderListVO> listByTimeToTime(OrderListTimeDTO orderListTimeDTO) {
        validateTimeLoadTime(orderListTimeDTO);
        orderListTimeDTO.setUserId(getUserId());
        //设置分页条件
        PageHelper.startPage(orderListTimeDTO.getPage(),orderListTimeDTO.getPageSize());
        List<OrderListVO> list = orderMapper.selectOrdersBetweenTimes(orderListTimeDTO);
        return JsonPage.restPage(list);
    }
    private void validateTimeLoadTime(OrderListTimeDTO orderListTimeDTO) {
        LocalDateTime startTime = orderListTimeDTO.getStartTime();
        LocalDateTime endTime = orderListTimeDTO.getEndTime();
        if(startTime == null || endTime == null){
            startTime = LocalDateTime.now().minusMonths(1);
            endTime = LocalDateTime.now();
            orderListTimeDTO.setStartTime(startTime);
            orderListTimeDTO.setEndTime(endTime);
        }else{
            // 如果start和end都非null
            // 就要判断start是否小于end,否则要抛出异常
            if(endTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()<
                    startTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()){
                // 如果判断表示结束时间小于开始时间,抛出异常
                throw new ServiceException(ServiceCode.ERR_BAD_REQUEST,
                        "结束时间应大于起始时间!");
            }
        }
    }

    private LoginPrincipal getUserInfo(){
        UsernamePasswordAuthenticationToken authenticationToken=
                (UsernamePasswordAuthenticationToken)
                        SecurityContextHolder.getContext().getAuthentication();
        if(authenticationToken == null){
            throw new ServiceException(
                    ServiceCode.ERR_UNAUTHORIZED,"您没有登录!");
        }
        LoginPrincipal loginPrincipal = (LoginPrincipal)authenticationToken.getPrincipal();
        return loginPrincipal;
    }
    private Long getUserId(){
        return getUserInfo().getId();
    }
}
